home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Word 6
/
The Word 6.adf
/
FiLeS
/
AMOS4.txt
/
AMOS4.txt
Wrap
Text File
|
2022-11-05
|
14KB
|
319 lines
|AMOS Programming Tutorial
by Freak of NFA
Hopefully you're following this little tutorial/hint guide okay and my
explanations and methods don't leave you thinking "what the bloody hell
is HE smoking man?", certainly nobody has written to me saying that they
can't follow them, I assume then that things are progressing smoothly...
|Part 4 - Text Files
One of the things I've been asked about a lot recently is how to include
ASCII text files in AMOS programs, mainly by people wanting to create
their own disk-lists or disk-based magazines but getting stuck at this
point. It may sound laughable - "just load it in!" I hear you cry - but
getting it to work, and more importantly getting it to work FAST, can be
bloody infuriating without some help.
I've been using the same method for a while now, I've leaked the odd
secret or two to a couple of people but now with this new-found sense of
open-ness and honesty, I feel it's time to let you have the full low-
down on how to get text files into your programs.
|Loading...
Before we can start doing things with the text file we've obviously got
to get it loaded into AMOS, into a bank where we can get our hands on it
more easily. Sifting through data in RAM is immensly quicker than doing
the same with a disk so it makes sense to load the whole file in first
rather than load one line at a time from disk, right? The obvious draw-
back with this is that the memory usage will be higher, but you'll
simply have to make sure you have sufficient room left for it, and in
all honesty, usage isn't too bad.
To load the file in:
'------------------------------------ Load file into bank 10
FILE$="Docs/MyTextFile.txt"
Open in 1,FILE$
Reserve as Work 10,Lof(1)
Bload FILE$,Start(10)
Close 1
The filename is stored in FILE$, you open channel one to it, reserve as
much RAM as you need for this RAW bank, load it in as Binary data, and
close the channel. Another good thing about this method is that you can
crunch your text file using Powerpacker or Crunchmania and with the
relevent patch you can load the file in as normal, making for great
savings in filespace. The Word uses Crunchmania and the RTDD patch
until we can get the Assembler source sorted out.
You'll decide exactly what FILE$ will hold through some sort of menu or
from a keypress, anything that lets the user make a decision. In The
Word it's taken from the y-position of the selector bar, added to the
lines that the screen is actually offset (if you've scrolled it down for
example), how you decide which file to load is up to you.
Because this file has been loaded as binary data it has not been split
into seperate lines, and so if you look into RAM you'll find that the
strings (individual text lines) are all in one big continuous block, and
seperated by character 10 - the EOL character. Just because these 10's
are there doesn't mean to say your text is already formatted!
Your startup-sequence may look like this in CygnusEd:
(fig.1)
.-------------------------------------------------------------.
| Makedir RAM:ENV RAM:ENV/Sys RAM:T |
| |
| Assign ENV: RAM:ENV |
| Assign A: SYS:A |
| Assign T: Ram:T |
| Assign Utils: SYS:Utilities/ |
| |
| CopyMemQuicker >Nil: |
| NoKlik >Nil: |
| CacheFont >Nil: |
| |
| Run >Nil: C:FreakBoot |
| Endcli >Nil: |
| |
|<------------------- Width of text Page -------------------->|
`-------------------------------------------------------------'
But as far as your memory is concerned it will look like this: (I have
used "#" in place of the character 10's...)
(fig.2)
.-------------------------------------------------------------.
|Makedir RAM:ENV RAM:ENV/Sys RAM:T##Assign ENV: RAM:ENV#Assign|
|A: SYS:A#Assign T: Ram:T#Assign Utils: SYS:Utilities/##CopyMe|
|mQuicker >Nil:#NoKlik >Nil:#CacheFont >Nil:##Run >Nil: C:Frea|
|kBoot#Endcli >Nil: |
| |
| |
|<---------------- Width of your Memory Block --------------->|
`-------------------------------------------------------------'
Remember, although I have conveniently slotted the above into a "block"
of memory x-bytes wide it is actually a continuous lump, and the width
divisions do not physically exist. You can see the above string by
going to direct mode and typing:
Print Peek$(Start(10),Length(10)) <Return>
What we have to do is "format" the RAW bank file into something that
represents the CygnusEd screen in fig.1 and we need to do it fast, as
our document may contain a lot of lines, and we don't want to keep our
user waiting while we crawl through a massive file!
|Counting Lines...
You see this line appear in PPMore and Opus, "Counting Lines" it says,
BOLLOCKS! I say, what it's really doing is formatting your text into
something useable!
You DO actually have to count the number of lines in your text file
before you can start to play with it, and this can be handled quite
easily with the following little routine:
'----------------------------------------------- Count Lines
POS=Start(10) : LINES=0
Do
Exit If POS>=Start(10)+Length(10)
H=Hunt(POS To Start(10)+Length(10),Chr$(10))
Exit If H=0 or H=Start(10)+Length(10)
Inc LINES
POS=H+1
Loop
In this bit, you start at the beginning of bank 10 and keep track of
where you are in the bank with the POS variable. The Hunt() function is
a bloody quick way of looking for a specific value, and to count the
number of lines in our doc all we have to really do is count the number
of times Chr$(10) appears, character 10 is the End Of Line (EOL) char,
remember? If you've found one, and you haven't reached the end of the
bank (Start(10)+Length(10)) then you set POS to one PAST the EOL char
that you've just found and continue your search.
When all is done, the LINES variable will hold the number of lines in
your document, now you can start chopping bank 10 up into something more
managable, individual lines.
'------------------------------------- Text into TXT$()
POS=Start(10)
Dim TXT$(LINES)
For LINE=1 To LINES
H=Hunt(POS To Start(10)+Length(10),Chr$(10))
TL=1+(H-POS) : TXT$=Space$(TL)
Copy POS,POS+TL To Varptr(TXT$)
TXT$(LINE)=TXT$-Chr$(10)
POS=H+1
Next LINE
The more astute of you will realise that these last two routines are
incredibly similar, that both use the Hunt() function in exactly the
same way so can they be combined into one loop instead of two? Well,
they can if you have the same memory area reserved for each of your
files, but that would mean having to reserve memory for the biggest file
that you've got ALL the time.
The speed that you require is gained from using the Amiga Blitter chip
to format your text with the Copy command. In the above you reserve a
place to put your new line (T$=Space$(), above) and copy the data into
it at the highest speed possible.
You'll see above that I have put the lines of text into an array called
(not suprisingly) TXT$(). This method would be used for something that
would only need defining once, like the menu on a disk-mag, because you
don't want to have to call Dim TXT$() for each document, it is very
wasteful and slow as far as RAM is concerned.
The other way to do it is to format the RAW bank into another bank, and
then take the data from this bank as you need it. You would replace a
few of the lines of the above routine but the essential functionality
remains the same. The altered routine goes like this:
'------------------------------------- Text into Bank 11
POS=Start(10) : PAGEWIDTH=60
Reserve as Work 11,LINES*PAGEWIDTH
'----------------------------------- Fill bank with Spaces
A$=" " : Fill Start(11),Start(11)+Length(11),Leek(Varptr(A$))
For LINE=1 To LINES
H=Hunt(POS To Start(10)+Length(10),Chr$(10))
TL=(H-POS) : If TL>PAGEWIDTH Then TL=PAGEWIDTH
Copy POS,POS+TL To Start(11)+((LINE-1)*PAGEWIDTH)
POS=H+1
Next LINE
This one is not only much, much faster than the above, but there's no
slow-down where AMOS performs a garbage-collection run due to excessive
use of strings by your program, so this is ideal for articles and the
like, the bank can be erased when you've finished with it, and you have
complete control over every byte.
|Outputting Text...
Now that you've got your text file in RAM in a format that you can
easily get at, it's time to give the user something to look at, and
because you have your text all nicely formatted and available, this is
the easiest thing in the world!
==========
Example 1:
==========
You want to display a certain page of the menu in your disk-mag, there
are LPP Lines on each page (LPP = Lines Per Page) and you want the text
lines 10 pixels apart so that you can do a nice copper bar effect to
follow your mouse pointer for a selection method:
Easy! You've formatted each line into an array called TXT$() because
you want to be able to use the strings in this array as headers as well,
so getting any particular line is as easy as looking in the array!
T$=TXT$(LINE)
Print T$
Was that so difficult? No.
To display the menu page you need to define a start line and an end line
depending on LPP (Lines Per Page) and the actual page number:
'------------------------------------------ Setup Values
LPP=15 : PAGE=1 : XPOS=20
PAGES=LINES/LPP : If PAGES*LPP<>LINES Then Inc PAGES
'----------------------------------------- Start and End lines
ST=(PAGE-1)*LPP
ND=ST+LPP-1 : IF ND>LINES Then ND=LINES
'---------------------------------------- Display the Page
For LINE=ST To ND
YPOS=20+((LINE-1)*10)
T$=TXT$(LINE)
Text XPOS,YPOS,T$
Next LINE
All you really have to watch out for is the PAGE variable, make sure
that there is no way it can go above the actual number of pages that you
have got, which is stored in PAGES, and that it doesn't go below 1, if
it does either of these things you'll get an error.
==========
Example 2:
==========
Your user has selected an article and you've loaded it, formatted it
into bank 11, and now you want to display the first page. There are now
TLPP lines on each article page (TLPP = Text Lines Per Page) and you
want the lines every 8 pixels so that all your funky ASCII logos look
dead groovy with no silly lines...
'--------------------------------------------- Setup Values
TLPP=20 : SHEET=1 : PAGEWIDTH=60
SHEETS=TLINES/TLPP : If SHEETS*TLPP<>TLINES Then Inc SHEETS
'----------------------------------------- Start and End lines
ST=(SHEET-1)*TLPP
ND=ST+LPP-1 : IF ND>TLINES Then ND=TLINES
'---------------------------------------- Display the Page
For TLINE=ST To ND
YPOS=20+((TLINE-1)*8)
T$=Space$(PAGEWIDTH)
SRC=Start(11)+((SHEET-1)*(TLPP*PAGEWIDTH))+((TLINE-1)*PAGEWIDTH)
Copy SRC,SRC+(PAGEWIDTH-1) To Varptr(T$)
Text XPOS,YPOS,T$
Next TLINE
This one is a little more complicated that before, because again you are
using the blitter to grab your lines of text straight out of the RAM
bank and put them straight into T$, as quickly as possible. I've also
used new variables, SHEET, SHEETS, TLINES, and TLPP in place of others
so that you don't end up using the same variables for different things
and so get yourselves into a mess:
SHEET - Instead of PAGE, it contains the current SHEET number
SHEETS - Instead of PAGES, contains the maximum number of SHEETS
TLINES - Replaces LINES, just the number of lines in the article
TLPP - Aready explained, the number of lines of text on each page
The same wornings apply as in Example1, in that you should not let the
SHEET variable go above SHEETS or below 1, otherwise you risk crashing
your Amiga completely!
The Word uses a mixture of these two for the Menu, and uses a variation
of Example 2 for it's articles, so you can see that these routines work
absolutely fine. That said I haven't TESTED any of the above code, the
formatting routines were from "Balls!" so they should work fine, but the
output routines I just made up off the top of my head, so if they don't
work, FIX THE BUGGERS!
If you have any suggestions to make with regards to improving my source
code or you've found bugs due to my lack of testing, write in to me at
the usual address and I'll publish an amendment in the next issue. If
you've written something incredible and you want to share it with the
rest of the Amiga/AMOS world, this is the place to send it!
Have fun people!!!
|Freak of NFA
Support the Amiga - Kill the Consoles!